﻿namespace KinonekoSoftware.Studio.Models.Modules
{
    public sealed class OptionElementPresenter : ModulePresenter
    {
        private static readonly Primitive_Option Empty = new Primitive_Option { Id = "Error", Name = "错误的值", Value = "错误的值" };
        private readonly        Element_Option   _AssociatedObject;

        private string           _value;
        private Primitive_Option _item;
        private bool             _isValue;

        public OptionElementPresenter()
        {
            NewOptionCommand = new ActionCommand(DoAddOptionChildCommand);
            ShiftUpCommand   = new FuncCommand<Primitive_Option>(DoShiftUpOptionCommand);
            ShiftDownCommand = new FuncCommand<Primitive_Option>(DoShiftDownOptionCommand);
            RemoveCommand    = new FuncCommand<Primitive_Option>(DoRemoveOptionCommand);
        }


        /// <summary>
        /// 获得当前内容块的标题。
        /// </summary>
        /// <returns>返回当前内容块的标题。</returns>
        public override string GetTitle() => string.IsNullOrEmpty(Title) ? CodariaSR.Module_Element_Option : Title;
        public override bool IsMultipleVariants() => false;
        public override IEnumerable<Variant> GetVariants(string documentID) => null;
        public override Variant GetVariant(string documentID)
        {
            return new StringVariant
            {
                Id       = documentID,
                Metadata = Metadata,
                Value    = Value,
                Type     = VariantType.String,
            };
        }
        
        
        public override void DataSync(Variant variant)
        {
            if (variant is StringVariant sv)
            {
                var item = Items.FirstOrDefault(x => x.Value == sv.Value || x.Name == sv.Value);

                if (item is null)
                {
                    return;
                }
                
                Value = item.Value;
            }
        }


        private void OnInitialize(Element_Option target)
        {
            Items.AddMany(target.Items, true);
            SelectedItem = Items.FirstOrDefault(x => x.Id == target.ValueID) ?? Empty;
            RaiseUpdated(nameof(SelectedItem));
        }


        private void DoAddOptionChildCommand()
        {
            var target = new Primitive_Option { Id = ID.Get(), Name = "Untitled", Value = "Untitled" };

            Items.Add(target);
            AssociatedObject.Items.Add(target);
        }

        private void DoShiftDownOptionCommand(Primitive_Option target)
        {

            if (target is null || SelectedItem is null)
            {
                return;
            }

            Items.ShiftDown(target);
            AssociatedObject.Items.ShiftDown(target);
        }

        private void DoShiftUpOptionCommand(Primitive_Option target)
        {

            if (target is null || SelectedItem is null)
            {
                return;
            }

            Items.ShiftUp(target);
            AssociatedObject.Items.ShiftUp(target);
        }

        private async void DoRemoveOptionCommand(Primitive_Option target)
        {

            if (target is null || SelectedItem is null)
            {
                return;
            }

            if (!await RemoveItem())
            {
                return;
            }

            Items.Remove(target);
            AssociatedObject.Items.Remove(target);
        }

        public string Metadata
        {
            get => AssociatedObject?.Metadata;
            set
            {
                if (AssociatedObject is null)
                {
                    return;
                }


                if (string.IsNullOrEmpty(value))
                {
                    Queue?.OnNext(new MetadataChangedMSG
                    {

                        Block     = TopLevel,
                        Element   = this,
                        IsRemoved = true,
                        OldSpell  = AssociatedObject.Metadata,
                        NewSpell  = null,
                    });
                }
                else
                {
                    Queue?.OnNext(new MetadataChangedMSG
                    {
                        Block     = TopLevel,
                        Element   = this,
                        IsRemoved = true,
                        OldSpell  = AssociatedObject.Metadata,
                        NewSpell  = value,
                    });
                }

                AssociatedObject.Metadata = value;
                RaiseUpdated();
            }
        }

        public string Value
        {
            get => _value;
            set
            {
                if (AssociatedObject is null)
                {
                    return;
                }

                SetValue(ref _value, value);

                Queue?.OnNext(new ValueChangedMSG
                {
                    Block      = TopLevel,
                    Element    = this,
                    Metadata = Metadata,
                });
            }
        }
        
        public string Id => AssociatedObject?.Id;

        public required Element_Option AssociatedObject
        {
            get => _AssociatedObject;
            init
            {
                if (value is null)
                {
                    return;
                }

                _AssociatedObject = value;
                OnInitialize(value);
            }
        }

        public string Description
        {
            get => AssociatedObject?.Description;
            set
            {
                if (AssociatedObject is null)
                {
                    return;
                }

                AssociatedObject.Description = value;
                RaiseUpdated();
            }
        }

        public string Title
        {
            get => AssociatedObject?.Title;
            set
            {
                if (AssociatedObject is null)
                {
                    return;
                }

                AssociatedObject.Title = value;
                RaiseUpdated();
            }
        }

        public required ModulePresenter TopLevel { get; init; }

        public Primitive_Option SelectedItem
        {
            get => _item;
            set
            {
                if (value is null)
                {
                    return;
                }

                SetValue(ref _item, value);
                _isValue = SelectedItem?.Id == AssociatedObject.ValueID;
                RaiseUpdated(nameof(IsValue));
            }
        }


        /// <summary>
        /// 获取或设置 <see cref="IsValue"/> 属性。
        /// </summary>
        public bool IsValue
        {
            get => _isValue;
            set
            {
                SetValue(ref _isValue, value);

                if (value)
                {
                    AssociatedObject.ValueID = SelectedItem.Id;
                    Value = SelectedItem.Value;
                }
            }
        }

        public ObservableCollection<Primitive_Option> Items { get; } = new ObservableCollection<Primitive_Option>();

        public     ICommandEX NewOptionCommand { get; }
        public new ICommandEX ShiftUpCommand   { get; }
        public new ICommandEX ShiftDownCommand { get; }
        public new ICommandEX RemoveCommand    { get; }
    }
}